/**
 * 
 */
package com.williamoneil.charts.client.widget.helper;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.williamoneil.charts.client.data.ChartBoundsRect;
import com.williamoneil.charts.client.data.DateAxis;
import com.williamoneil.charts.client.data.HorizontalGridLine;
import com.williamoneil.charts.client.data.PriceAxis;
import com.williamoneil.charts.client.data.Tick;
import com.williamoneil.charts.client.data.VerticalGridLine;
import com.williamoneil.charts.client.util.ChartUtil;
import com.williamoneil.charts.shared.PeriodicityType;
import com.williamoneil.charts.shared.TradeDateType;

/**
 * @author gudipati
 *
 */
public class WeeklyChartHelper implements IChartHelper{

	private DateAxis dateAxis = null;
	private PriceAxis priceAxis = null;
	private ChartBoundsRect chartBounds = null;
	private List<Tick> ticks;
	private boolean linear = false;
	private int tickSpacing = ChartUtil.DEFAULT_TICK_SPACING;
			
	public WeeklyChartHelper(final ChartBoundsRect bounds, final List<Tick> ticks, final boolean isLinear, final int tickSpacing) {
		this.chartBounds = bounds;
		this.ticks = ticks;
		this.linear = isLinear;
		this.tickSpacing = tickSpacing;
		// IMPORTANT: DONT INSTANTIATE DATE & PRICE AXIS HERE Since MAX/MIN are not initialized yet
	}
	
	private boolean stopProcessing = false;
	
	private List<VerticalGridLine> verticalGridLines = new ArrayList<VerticalGridLine>();
	private List<HorizontalGridLine> horizontalGridLines = null;
	
	BigDecimal minVal = BigDecimal.valueOf(Long.MAX_VALUE);
	BigDecimal maxVal = BigDecimal.ZERO;
	
	private Tick lastOne = null;
	private int indexOfTheMonth = 0;
	//private int indexOfTheYear = 0;
	
	@SuppressWarnings("deprecation")
	public void processTick(final Tick currOne) {
		if(stopProcessing) {
			return;
		}
		
		// first check if we are within the bounds (date-wise)
		final Date tradeDt = currOne.getDate();
		int x = getDateAxis().getX(tradeDt);
		if(x < chartBounds.getX()) {
			// we stop if we are beyond the ticks we can draw on chart
			stopProcessing = true;
			return;
		}
		
		VerticalGridLine aGL = null;
				
		// first tick of the month we draw a major grid-line
		if(lastOne != null) {
			if(indexOfTheMonth <= 18 && lastOne.getDate().getMonth() != currOne.getDate().getMonth()) {
				if(aGL == null) {
					aGL = new VerticalGridLine();
				}
			
				aGL.setMajor(false);
				indexOfTheMonth++;
			}
			if(lastOne.getDate().getYear() != currOne.getDate().getYear()) {
				if(aGL == null) {
					aGL = new VerticalGridLine();
				}
				
				aGL.setMajor(true);
				//indexOfTheYear++;
			}
		}
		
		if(aGL != null) {
			if(lastOne != null) {
				aGL.setValue(lastOne.getDate());
			} else {
				aGL.setValue(currOne.getDate());
			}
			verticalGridLines.add(aGL);
		}
		
		//check min-max
		if(currOne.getTradeDateType() == TradeDateType.TRADE_DATE) {
			if(currOne.getPrice().getHigh() != null && currOne.getPrice().getHigh().compareTo(maxVal) > 0) {
				maxVal = currOne.getPrice().getHigh();
			}
			if(currOne.getPrice().getLow() != null && currOne.getPrice().getLow().compareTo(minVal) < 0) {
				minVal = currOne.getPrice().getLow();
			}
		}

		
		lastOne = currOne;
		stopProcessing = false;
	}
	

	/**
	 * @return the verticalGridLines
	 */
	public List<VerticalGridLine> getVerticalGridLines() {
		return verticalGridLines;
	}

	@Override
	public DateAxis getDateAxis() {
		if(dateAxis == null) {
			this.dateAxis = new DateAxis(chartBounds, ticks, PeriodicityType.Weekly, tickSpacing);
		}

		return dateAxis;
	}

	@Override
	public PriceAxis getPriceAxis() {
		if(priceAxis == null) {
			this.priceAxis = new PriceAxis(minVal.doubleValue(), maxVal.doubleValue(), linear);
		}
		return priceAxis;
	}

	@Override
	public List<HorizontalGridLine> getHorizontalGridLines() {
		if(horizontalGridLines == null) {
			horizontalGridLines = getPriceAxis().getHorizontalGridLines(chartBounds);
		}
		return horizontalGridLines;
	}
	
	/**
	 * @return the linear
	 */
	public boolean isLinear() {
		return linear;
	}
}
